


#include "esp_spiffs.h"
#include "esp_vfs_fat.h"  // 添加这一行以修复未定义标识符错误
#include "wear_levelling.h"
#include "esp_log.h"
#include <stdio.h>
#include <string.h>
#include <sys/stat.h>
#include <dirent.h>


/**

          
`read_embedded_files_fat_spiffs.c` 文件是一个ESP32项目中的主要应用文件，
主要负责配置、挂载和管理两种不同的文件系统：SPIFFS（SPI Flash File System）和FAT文件系统。

该文件的核心功能包括：

1. **文件系统配置与挂载**：
   - 配置SPIFFS文件系统（挂载点`/spiffs`，分区标签`spiffs_partition`）
   - 配置FAT文件系统（挂载点`/fat`，分区标签`storage`）
   - 实现两种文件系统的注册和挂载逻辑

2. **文件系统状态检查与错误处理**：
   - 检查SPIFFS分区是否已格式化，若未格式化则尝试手动格式化
   - 处理FAT文件系统挂载失败的情况，尝试进行格式化修复
   - 提供详细的错误日志记录，便于调试

3. **文件系统信息获取**：
   - 获取SPIFFS分区的总大小和已使用大小
   - 实现`list_spiffs_files`函数，用于遍历并显示指定目录下的所有文件和子目录

4. **文件内容访问**：
   - 列出多个关键目录（根目录、data目录、spiffs目录、www子目录、fat目录）的文件列表
   - 读取并显示特定文件（如`/fat/fatlivon.txt`）的内容

这个文件在ESP32的存储系统开发中起到了测试和验证的作用，能够帮助开发者确认文件系统是否正确配置、挂载成功，并能够正常读写文件。
        
 */

static const char *TAG = "spiffs_check";

/**
 * @brief 列出SPIFFS文件系统指定目录下的所有文件和目录
 *
 * 该函数用于遍历并显示SPIFFS文件系统中指定路径下的所有文件和子目录名称
 * 对于调试文件系统操作和验证文件是否正确创建非常有用
 *
 * @param base_path 要列出内容的目录路径，如"/spiffs"
 */
void list_spiffs_files(const char *base_path)
{
    // 尝试打开指定目录
    DIR *dir = opendir(base_path);

    // 打印当前路径，用于调试
    ESP_LOGI(TAG, "当前路径: %s", base_path);

    // 检查目录是否成功打开
    if (!dir)
    {
        ESP_LOGE(TAG, "无法打开目录 %s", base_path);
        return; // 打开失败，直接返回
    }

    // 目录项结构体，用于存储读取到的文件/目录信息
    struct dirent *entry;

    // 循环读取目录中的所有条目，直到没有更多条目可读
    while ((entry = readdir(dir)) != NULL)
    {
        // 记录找到的每个文件/目录名称
        ESP_LOGI(TAG, "找到文件: %s", entry->d_name);
        // 打印文件内容
        char file_path[256];
        int written = snprintf(file_path, sizeof(file_path), "%s/%s", base_path, entry->d_name);
        if (written < 0 || written >= sizeof(file_path))
        {
            ESP_LOGW(TAG, "路径过长，跳过文件: %s", entry->d_name);
            continue;
        }
        FILE *f = fopen(file_path, "r");
        if (f)
        {
            char line[256];
            while (fgets(line, sizeof(line), f))
            {
                // ESP_LOGI(TAG, "文件内容: %s", line);
            }
            fclose(f);
        }
    }

    // 关闭目录，释放资源
    closedir(dir);
}

/**
 * @brief 应用程序主入口函数
 * @details 该函数负责配置并尝试挂载SPIFFS文件系统分区，处理挂载结果，
 *          若挂载成功则获取分区信息并列出文件，若分区未格式化则尝试格式化
 */
void app_main(void) {
    // SPIFFS文件系统配置结构体
    esp_vfs_spiffs_conf_t conf = {
      .base_path = "/spiffs",           // 文件系统挂载点路径
      .partition_label = "spiffs_partition", // 分区标签（与分区表中定义的保持一致）
      .max_files = 5,                   // 同时打开的最大文件数
      .format_if_mount_failed = false   // 关键：设置为false，表示挂载失败时不自动格式化
    };

    ESP_LOGI(TAG, "尝试挂载 SPIFFS 分区...");
    // 注册并挂载SPIFFS文件系统
    esp_err_t ret = esp_vfs_spiffs_register(&conf);
    
    if (ret == ESP_OK) {
        ESP_LOGI(TAG, "SPIFFS 分区已格式化，挂载成功！");
        // 获取分区的总大小和已使用大小信息
        size_t total = 0, used = 0;
        ret = esp_spiffs_info("spiffs_partition", &total, &used);
        if (ret == ESP_OK) {
            ESP_LOGI(TAG, "分区大小：%d 字节，已使用：%d 字节", total, used);
        }
        
        // 列出不同路径下的文件，验证文件系统内容
        list_spiffs_files("/");           // 根目录
        list_spiffs_files("/data");       // data目录（若存在）
        list_spiffs_files("/spiffs");     // SPIFFS挂载点目录
        list_spiffs_files("/spiffs/www"); // www子目录（若存在）

        // 卸载SPIFFS分区（演示目的）
        esp_vfs_spiffs_unregister("spiffs_partition");
    } else if (ret == ESP_FAIL) {
        ESP_LOGE(TAG, "SPIFFS 分区未格式化或已损坏！");
        // 尝试手动格式化分区
        ret = esp_spiffs_format("spiffs_partition");
        if (ret == ESP_OK) {
            ESP_LOGI(TAG, "SPIFFS 分区格式化成功！");
        } else {
            ESP_LOGE(TAG, "格式化 SPIFFS 分区失败：%s", esp_err_to_name(ret));
        }
    } else {
        ESP_LOGE(TAG, "挂载 SPIFFS 分区失败：%s", esp_err_to_name(ret));
    }


    

    // FAT 文件系统挂载配置结构体
    esp_vfs_fat_mount_config_t fat_mount_config = {
        .format_if_mount_failed = false,
        .max_files = 5,
        .allocation_unit_size = 4096
    };

    ESP_LOGI(TAG, "尝试挂载 FAT 文件系统...");
    // 注册并挂载FAT文件系统
    wl_handle_t wl_handle;
    ret = esp_vfs_fat_spiflash_mount_rw_wl("/fat", "storage", &fat_mount_config, &wl_handle);
    if (ret != ESP_OK) {
        // 打印 ret
        ESP_LOGI(TAG, "挂载结果：%s", esp_err_to_name(ret));
        ESP_LOGE(TAG, "挂载 FAT 文件系统失败：%s", esp_err_to_name(ret));
        // 尝试手动格式化分区
        // ret = esp_fat_format("fat_data");
        // 替换第132行左右的 esp_fat_format 调用为正确的 FAT 格式化函数
        // ret = esp_vfs_fat_spiflash_format_rw_wl("fat_data");
        ret = esp_vfs_fat_spiflash_format_rw_wl("fat_data", "storage");
        // 打印格式化结果
        ESP_LOGI(TAG, "格式化结果：%s", esp_err_to_name(ret));
        if (ret == ESP_OK) {
            ESP_LOGI(TAG, "FAT 分区格式化成功！");
        } else {
            ESP_LOGE(TAG, "格式化 FAT 分区失败：%s", esp_err_to_name(ret));
        }
    } else {
        ESP_LOGI(TAG, "FAT 文件系统挂载成功！");
        list_spiffs_files("/fat");
        // 显示 /fat/fatlivon.txt 文件内容
        const char *fat_file_path = "/fat/fatlivon.txt";
        FILE *f = fopen(fat_file_path, "r");
        if (f) {
            char line[256];
            while (fgets(line, sizeof(line), f)) {
                ESP_LOGI(TAG, "文件内容: %s", line);
            }
            fclose(f);
        } else {
            ESP_LOGE(TAG, "打开文件 %s 失败", fat_file_path);
        }
    }
}